June 25, 2020
추가적인 item은 오른쪽 스와이핑 액션을 통해 해당 페이지로 넘어가야함
touchmove(스와이핑)이벤트가 발생해는 x값에 따라 퍼센테이지를 UI로 제공
ngAfterViewInit() {
this._sub.push(
this.result$.pipe(
tap(result => this.result = result),
filter((result) => result && result.total > result.listNum),
switchMap(() => this.swipeToSeeMore())
).subscribe()
);
}touchmove event를 감지해서 스크롤이 끝에 도달할 경우 이벤트를 전파한다. touchend 이벤트가 발생하면 원하는 주소로 이동한다.touchend이벤트가 발생하면 translateX값 및 strokeDasharray 값을 초기화한다.private swipeToSeeMore() {
const element = this.elementRef.nativeElement;
const circle = this.circle.nativeElement;
let reqId, percentage, touchStartX;
return combineLatest([
fromEvent(element, 'touchmove', { passive: true }).pipe(
filter(() => {
const { scrollWidth, scrollLeft, clientWidth } = element;
return scrollWidth - scrollLeft - clientWidth <= 0;
}),
map((touchMove: TouchEvent) => touchMove.changedTouches[0].clientX),
tap((x) => touchStartX = touchStartX || x),
tap((x) => {
// 디바이스 가로폭 40%까지만 swipe 하면 100%
const xThreshold = element.clientWidth * 0.4;
const xDiff = touchStartX - x;
percentage = Math.min(xDiff, xThreshold) / xThreshold;
reqId = cancelAndRequestAnimationFrame(reqId, () => {
// transform을 이용해 안드로이드 디바이스에서도 스와이핑이 되게 구현
element.style.transform = `translateX(-${xDiff / 2}px)`;
circle.style.strokeDasharray = `${Math.round(percentage * 100)}, 100`;
});
})
),
fromEvent(element, 'touchend', { passive: true }).pipe(
tap(() => {
if (percentage >= 1) {
this.router.navigate(this.navigateUrl);
} else {
reqId = cancelAndRequestAnimationFrame(reqId, () => {
element.style.transform = `translateX(0px)`;
circle.style.strokeDasharray = `0, 100`;
});
}
touchStartX = 0;
})
)
]);
};이 밖에도 strokeDasharray, requestAnimationFrame 등 이 기능을 구현 및 최적화하기 위해 알아야할 지식들이 있다. 참고할 문서들이 많으니 링크로 남겨 놓겠다.
참고 및 출처